package com.liy.framework.common.web.exception;

import com.liy.framework.common.exception.BusinessException;
import com.liy.framework.common.extvo.ResponseVo;
import com.liy.framework.common.extvo.ResultVO;
import com.fasterxml.jackson.databind.ObjectMapper;
import io.jsonwebtoken.MalformedJwtException;
import java.util.Iterator;
import java.util.Set;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.MessageSource;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.ModelAndView;

@ControllerAdvice
public class GlobalExceptionHandler {
    @Autowired
    MessageSource messageSource;

    public GlobalExceptionHandler() {
    }

    @ExceptionHandler({Exception.class})
    public Object defaultErrorHandler(HttpServletRequest request, HttpServletResponse response, Exception e) throws Exception {
        String accept = request.getHeader("Accept");
        boolean ajax = true;
        if (!ajax && accept != null && !accept.contains("json")) {
            ModelAndView view = new ModelAndView();
            view.addObject("message", e.getMessage());
            view.addObject("success", false);
            view.addObject("status", this.getStatus(request).value());
            view.addObject("path", request.getRequestURL());
            view.addObject("timestamp", System.currentTimeMillis());
            view.setViewName("error");
            return view;
        } else {
            ResultVO resultVO = new ResultVO(false);
            resultVO.setMessage(e.getMessage());
            resultVO.put("status", this.getStatus(request).value());
            resultVO.put("path", request.getRequestURL().toString());
            resultVO.put("timestamp", System.currentTimeMillis());
            response.flushBuffer();
            response.setCharacterEncoding("UTF-8");
            response.setContentType("application/json");
            ServletOutputStream outputStream = response.getOutputStream();
            outputStream.write((new ObjectMapper()).writeValueAsString(resultVO).getBytes("UTF-8"));
            outputStream.flush();
            return null;
        }
    }

    @ExceptionHandler({BusinessException.class})
    @ResponseBody
    public ResultVO jsonErrorHandler(HttpServletRequest request, BusinessException e) throws Exception {
        ResultVO resultVO = new ResultVO(false);
        resultVO.setMessage(e.getMessage());
        resultVO.put("status", this.getStatus(request).value());
        resultVO.put("path", request.getRequestURL());
        resultVO.put("timestamp", System.currentTimeMillis());
        return resultVO;
    }

    @ExceptionHandler({MalformedJwtException.class})
    @ResponseBody
    public ResultVO jwtTokenErrorHandler(HttpServletRequest request, MalformedJwtException e) throws Exception {
        ResultVO resultVO = new ResultVO(false);
        resultVO.setMessage("非法的认证请求");
        resultVO.put("status", "401");
        resultVO.put("path", request.getRequestURL());
        resultVO.put("timestamp", System.currentTimeMillis());
        return resultVO;
    }

    @ExceptionHandler({ApiParamValidatorException.class})
    @ResponseBody
    public ResponseVo apiParamValidatorExceptionHandler(HttpServletRequest request, ApiParamValidatorException e) throws Exception {
        return ResponseVo.error(e.getCode(), e.getMessage());
    }

    @ExceptionHandler({NoPermissionException.class})
    @ResponseBody
    public ResultVO noPermissionExceptionExceptionHandler(HttpServletRequest request, NoPermissionException e) throws Exception {
        ResultVO resultVO = new ResultVO(false);
        resultVO.setMessage(e.getMessage());
        resultVO.put("status", HttpStatus.FORBIDDEN.toString());
        resultVO.put("path", request.getRequestURL());
        resultVO.put("timestamp", System.currentTimeMillis());
        return resultVO;
    }

    @ExceptionHandler({NoAuthorizationException.class})
    @ResponseBody
    public ResultVO noAuthorizationExceptionHandler(HttpServletRequest request, NoAuthorizationException e) throws Exception {
        ResultVO resultVO = new ResultVO(false);
        resultVO.setMessage(e.getMessage());
        resultVO.put("status", HttpStatus.UNAUTHORIZED.toString());
        resultVO.put("path", request.getRequestURL());
        resultVO.put("timestamp", System.currentTimeMillis());
        return resultVO;
    }

    protected HttpStatus getStatus(HttpServletRequest request) {
        Integer statusCode = (Integer)request.getAttribute("javax.servlet.error.status_code");
        if (statusCode == null) {
            return HttpStatus.INTERNAL_SERVER_ERROR;
        } else {
            try {
                return HttpStatus.valueOf(statusCode);
            } catch (Exception var4) {
                return HttpStatus.INTERNAL_SERVER_ERROR;
            }
        }
    }

    @ExceptionHandler({ConstraintViolationException.class})
    @ResponseBody
    public ResultVO handleResourceNotFoundException(ConstraintViolationException e) {
        ResultVO resultVO = new ResultVO(false);
        Set<ConstraintViolation<?>> violations = e.getConstraintViolations();
        StringBuilder strBuilder = new StringBuilder();
        Iterator var5 = violations.iterator();

        while(var5.hasNext()) {
            ConstraintViolation<?> violation = (ConstraintViolation)var5.next();
            String str = violation.getPropertyPath().toString();
            strBuilder.append(str.substring(str.lastIndexOf(".") + 1)).append(":").append(violation.getMessage()).append(";");
        }

        resultVO.setStatus(HttpStatus.PRECONDITION_FAILED.toString());
        resultVO.setMessage(strBuilder.toString());
        return resultVO;
    }
}
